﻿//http://github.com/api/v2/json/repos/show/hakunin/

if (typeof(window.console) == 'undefined') {
  window.console = { 'log':function() {}, 'error':function() {} };
}
  


window.RubyIDE = (function() {

  var ideView = function(rootNode) {
    this.tabs = [];
    this.root = rootNode;
    this.el =  new YAHOO.util.Element(rootNode);

    this.render();
  }
  
  ideView.prototype.render = function() {
    this.tabView = new YAHOO.widget.TabView();
    //var child = this.el.appendChild(document.createElement('div'));
    //child.
    this.tabView.appendTo(this.el); 
  }
  
  ideView.prototype.addTab = function(tab) {
    this.tabs.push(tab);
    return tab;
  }

  ideView.prototype.addEditorTab = function(label, code) {
    return this.addTab(new editorTab(this.tabView, label, code));
  }

  var editorTab = function(tabView, label, code) {
    this.tabView = tabView;
    this.build(label, code);
  }
  
  editorTab.prototype.build = function(label, code) {
    var id = 'editor_'+Math.floor(Math.random()*1000000);
    this.tabView.addTab(new YAHOO.widget.Tab({ 
          label: label, 
          content: '<div class="editorTab" id="'+id+'"><div class="editor" ><textarea class="code" id="'+id+'_code" style="width:100%" rows="40">'+code+'</textarea><button class="run_button"/>run this!</button></div>'+
            '<div class="terminal">> <input type="text" class="command" value=""/><input type="submit" class="submit"/><div class="output"></div></div></div>', 
          active: true 
      }));
    //this.tab = this.tabView.getTab(0);
    console.log(id,this.tabView);
    this.content = new YAHOO.util.Element(id); 
    this.codetextarea = this.content.getElementsByClassName('code')[0];
    this.output = this.content.getElementsByClassName('output')[0];
    this.command = this.content.getElementsByClassName('command')[0];
    console.log(this.codetextarea, this.codetextarea.id);
    //console.log(this.content.getElementsByClassName('terminal'));
    this.codemirror = CodeMirror.fromTextArea(this.codetextarea.id, {
        parserfile: ["../../js/tokenizeruby.js", "../../js/parseruby.js"],
        stylesheet: "cm/css/rubycolors.css",
        path: "cm/codemirror/js/",
        lineNumbers: true,
        textWrapping: false,
        indentUnit: 2,
        tabMode: 'shift',
        parserConfig: {},
        height: '100%'
      });
    
    var run = new YAHOO.util.Element(this.content.getElementsByClassName('run_button')[0]);
    console.log('run', run);
    run.on('click', function(e, tab) {
      console.log('CLICK', tab);
      tab.runScript();
    }, this);
    var command = new YAHOO.util.Element(this.command);
    command.on('keydown', function(e, tab) {
      if (e.keyCode == 13) {
        console.log('CLICK', tab);
        tab.logLine('> '+tab.command.value);
        tab.runCode('p '+tab.command.value);
      }
    }, this);
  }

  editorTab.prototype.runCode = function(code) {
    //console.log('run', code);
    var json_result = (new Ruby()).evalToJson(code);
    console.log(json_result);
    this.logOutput(json_result);
  }

  editorTab.prototype.runScript = function() {
    this.runCode(this.codemirror.getCode());
  }

  editorTab.prototype.setCode = function(code) {
    //console.log('codemirror is ', this.codemirror);
    //window.codemirrorrrr= this.codemirror;
    this.codemirror.setCode(code);
  }
  
    editorTab.prototype.log = function(what, className) {
      what = what.split("\n");
      console.log(what);
      try {
      for (w in what) {
        if (YAHOO.lang.isString(what[w])) {
            if (what[w].match(/EXCEPTION:/)) {
              this.logLine(what[w].replace(/EXCEPTION:/, ''), 'exception');
            } else {
              this.logLine(what[w], className);
            }
        }
      }
      }catch (e) {
        console.log(e);
      }
    }

    editorTab.prototype.logLine = function(what, className) {
      what = what.replace(/[<&]/g, "$&<!>");
      what = what.replace(/\n/g, "<br />");    
      this.output.innerHTML += "<span class=\""+className+"\">"+what+"</span><br />";
      this.output.childNodes[this.output.childNodes.length-1].scrollIntoView();
    }


    editorTab.prototype.logOutput = function(output) {
      output = eval("("+output+")");
      if (typeof(output) == 'undefined') {
        output = 'no-output'; 
        this.log(output, 'result');
      } else {
        if (output['result']) {
          this.log(output['result'], 'result')
        }
        if (output['exception']) {
          this.log(output['exception'], 'exception')
          this.log(output['trace'], 'exception trace')
          console.log(output);
        }
      }    
    }



  
  
  
  
  var Ruby = function() {}
  Ruby.prototype.evalToJson = function(code) {
      code = 
        ["require 'stringio'\n",
        "$stdout = StringIO.new\n",
        //"begin\n",
        "eval('"+code.replace(/'/g, "\\'"),
        "', binding, 'sandbox', 0)\n",
        //"rescue Exception => e\n",
        //"puts 'EXCEPTION:' + $!.message+\"\\n\"+$!.backtrace.join(\"\\n\")\n",
        //"end\n",
        "$stdout.string"].join('');
        //console.log(code);
        
      return this._eval(code);
      //this.logLine('running sandbox.rb', 'system');
      //this.logOutput(this._evalRuby(code), 'result');
    }
    Ruby.prototype._eval = function(code) {
      try {
        return document.jrubyapplet.evalRubyToJson(code);
      } catch(e) {
        console.error(e);
        try {
          this.log(e.toString(), 'exception');
        } catch(e2) {        
          console.error(e2);
        }
      }
    }
    
    
/*
    editor.prototype.evalRuby = function(code) {
      this.log('> '+code, 'command');
      this.evalScript('p '+code);
    }

    editor.prototype.log = function(what, className) {
      what = what.split("\n");
      for (w in what) {
        if (what[w].match(/EXCEPTION:/)) {
          this.logLine(what[w].replace(/EXCEPTION:/, ''), 'exception');
        } else {
          this.logLine(what[w], className);
        }
      }
    }

    editor.prototype.logLine = function(what, className) {
      var output = document.getElementById('ruby_terminal_output');
      what = what.replace(/[<&]/g, "$&<!>");
      what = what.replace(/\n/g, "<br />");    
      output.innerHTML += "<span class=\""+className+"\">"+what+"</span><br />";
      output.childNodes[output.childNodes.length-1].scrollIntoView();
    }


    editor.prototype.logOutput = function(output) {
      console.log(output);
      console.log(output = eval("("+output+")"));    
      if (typeof(output) == 'undefined') {
        output = 'no-output'; 
        this.log(output, 'result');
      } else {
        if (output['result']) {
          this.log(output['result'], 'result')
        }
        if (output['exception']) {
          this.log(output['exception'], 'exception')
        }
      }    
    }

*/
  
  
  
  var ide = function(root_id) {
    this.root_id = root_id;
    console.log('wooot');
    this.initView();
    console.log('wooot');
  }

  ide.prototype.initView = function() {
    //new editor();
    this.view = new ideView(this.root_id);
  }
  return ide;
})();

